package com.googlecode.sere.translation

case class AcceptedTypes(ranges: Map[MediaRange, BigDecimal] = Map()) {

  def score(mediaType: MediaType): BigDecimal = {
    val matchingPairs = ranges map { entry =>
      val (range, score) = entry
      (range.matchType(mediaType), score)
    }
    val (_, maxScore) = ((0, BigDecimal("0.0")) /: matchingPairs) { (better, newOne) =>
      val (maxLevel, _) = better
      val (newLevel, newScore) = newOne
      if (newLevel > maxLevel) newOne else better
    }
    maxScore
  }

  /**
   * Returns None when every mediaType scores 0
   */
  def bestMatch(mediaTypes: Set[MediaType]): Option[MediaType] = {
    val scores = mediaTypes map { mt => (mt, score(mt)) }
    val (winner, _) = ((None: Option[MediaType], BigDecimal("0.0")) /: scores) { (better, newOne) =>
      val (_, maxScore) = better
      val (newType, newScore) = newOne
      if (newScore > maxScore) (Some(newType), newScore) else better
    }
    winner
  }

  override def toString(): String = {
    val formattedRanges = ranges map { case (range, q) => "%s;q=%s" format (range, q) }
    formattedRanges.mkString(", ")
  }
}

object AcceptedTypes {
  def apply(pairs: (MediaRange, BigDecimal)*): AcceptedTypes = new AcceptedTypes(Map(pairs:_*))
  def apply(mediaRange: MediaRange): AcceptedTypes = new AcceptedTypes(Map(mediaRange -> 1))
  def apply(mainType: String, subType: String): AcceptedTypes = apply(MediaRange(mainType, subType))
}